package whf.framework.report.export.filter;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.fop.apps.Driver;
import org.apache.fop.apps.Options;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.xml.sax.InputSource;

import whf.framework.log.Log;
import whf.framework.log.LogFactory;
import whf.framework.report.export.JasperExportHandler;
import whf.framework.report.export.util.ExportUtils;

public class ExportFilter implements Filter {
	private static Log log = LogFactory.getLog(ExportFilter.class);
	
	private String contentDisposition;
	
	private String pragma;
	
	private long expires;
	
	private Options opts;
	
	private JasperExportHandler jasperExportHandler;
	
	public void init(FilterConfig config)  throws ServletException {
		this.contentDisposition = config.getInitParameter("Content-Disposition");
		if(StringUtils.isEmpty(this.contentDisposition)){
			this.contentDisposition = "attachment";
		}
		this.pragma = config.getInitParameter("Pragma");
		if(StringUtils.isEmpty(this.pragma)){
			this.pragma = "public";
		}
		try{
			this.expires = Long.parseLong(config.getInitParameter("Expires"));
		} catch(Exception e){
			this.expires = 1000;
		}
		this.jasperExportHandler = new JasperExportHandler(config.getServletContext());
	}

	public void doFilter(ServletRequest request,
			ServletResponse response, FilterChain chain) throws IOException, ServletException {

        if (ExportUtils.isExportMode(request)) {
            String exportName = request.getParameter(ExportUtils.EXPORT_FILE_NAME);
            String exportType = request.getParameter(ExportUtils.EXPORT_TYPE);
            GenericResponseWrapper wrapper = new GenericResponseWrapper((HttpServletResponse) response);
            //
            chain.doFilter(request, wrapper);	//主要用于获取数据
            //
            //准备输出报表
            setResponseHeaders((HttpServletResponse) response, exportName);
            try{
	            if(StringUtils.equalsIgnoreCase(exportType, ExportUtils.PDF)){
	            	//handlePDF(request, response);
	            	HttpServletRequest req = (HttpServletRequest)request;
	            	HttpServletResponse res = (HttpServletResponse)response;
	            	this.jasperExportHandler.service(req, res);
	            } else if(StringUtils.equalsIgnoreCase(exportType, ExportUtils.XLS)){
	            	handleXLS(request, response);
	            } else if(StringUtils.equalsIgnoreCase(exportType, ExportUtils.TXT) || StringUtils.equalsIgnoreCase(exportType, ExportUtils.CSV)){
	            	handleTXT(request, response);
	            } else if(StringUtils.equalsIgnoreCase(exportType, ExportUtils.APPLET)){
	            	HttpServletRequest req = (HttpServletRequest)request;
	            	HttpServletResponse res = (HttpServletResponse)response;
	            	this.jasperExportHandler.service(req, res);
	            }
            }catch(Exception e){
            	log.error(this, e);
            	throw new ServletException(e);
            }
        } else {
            chain.doFilter(request, response);
        }
	}

	public void destroy() {

	}

    protected void handleXLS(ServletRequest request, ServletResponse response)
            throws Exception {
        HSSFWorkbook wb = (HSSFWorkbook)ExportUtils.getReportResult();
        if ( wb != null ) {
            wb.write(response.getOutputStream());
            response.getOutputStream().flush();
            response.getOutputStream().close();
        }
    }

    protected void handlePDF(ServletRequest request, ServletResponse response)
            throws Exception {
        String output = (String)ExportUtils.getReportResult();
        if ( output != null ) {
            InputStream is = new ByteArrayInputStream(output.getBytes("UTF-8"));
            renderFO(new InputSource(is), (HttpServletResponse) response);
        }
    }

    protected void handleTXT(ServletRequest request, ServletResponse response)
            throws Exception {
        String output = (String)ExportUtils.getReportResult();
        if ( output != null ) {
            byte[] content = output.getBytes();
            response.setContentLength(content.length);
            response.getOutputStream().write(content);
            response.getOutputStream().flush();
            response.getOutputStream().close();
        }
    }

    protected void renderFO(InputSource foFile, HttpServletResponse response)
            throws Exception {
    	if(opts == null){
	    	InputStream fis = ExportFilter.class.getClassLoader().getResourceAsStream("conf/pdf/userconfig.xml");
			opts = new Options(fis);
			fis.close();
    	}
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        Driver driver = new Driver(foFile, out);
        driver.setRenderer(Driver.RENDER_PDF);
        driver.run();

        byte[] content = out.toByteArray();
        response.setContentLength(content.length);
        response.getOutputStream().write(content);
        response.getOutputStream().flush();
        response.getOutputStream().close();
    }

    protected void setResponseHeaders(HttpServletResponse response, String exportName) {
        String mimeType = ExportUtils.getFileMimeType(exportName);
        if (StringUtils.isNotBlank(mimeType)) {
            response.setContentType(mimeType);
        }
        response.setHeader("Content-Disposition", this.contentDisposition+";filename=\"" + exportName + "\"");
        response.setHeader("Pragma", this.pragma);
        response.setDateHeader("Expires", (System.currentTimeMillis() + this.expires));
    }
}